release: v4.17.0 + MCPB connector bundle in the release workflow - #334
Merged
Conversation
Version surfaces moved 4.16.0 -> 4.17.0 across the nine sites that carry the release identity: pyproject.toml, server.json (document + pypi package), manifest.json, .claude-plugin/plugin.json, .claude-plugin/marketplace.json (metadata.version + the hypermnesia-mcp entry), uv.lock's root package, package.json, and the generated assets/badge-version.svg. The deprecated `cortex` marketplace entry stays pinned at 4.15.0 — it is a migration shim, not a shipped version. check_marketplace_pins.py, generate_repo_badges.py --check, and check_doc_claims.py all exit 0 on the result. CHANGELOG: the [Unreleased] block had accumulated 3x "### Fixed" and 2x "### Security" across merges, unlike every published section. Versioned as [4.17.0] with one sub-section per change type in Keep a Changelog order; content-preserving (verified by diffing the sorted multiset of body lines before and after — the only delta is the added dependency-bump entry). MCPB bundle: manifest.json and .mcpbignore already described a valid MCPB 0.4 bundle, but no workflow built one, so v4.14.3..v4.16.0 shipped zero release assets and the connector could only be produced by hand. The new `mcpb-bundle` job packs it on tag, verifies the manifest version matches the tag, publishes a sha256 companion, mints a Sigstore build-provenance attestation, and attaches a resolved server.json carrying both the pypi and the mcpb package entries — the mcpb entry needs the asset URL and its digest, neither of which exists before the build, which is why the committed server.json keeps only the version-addressable pypi package. The CLI is installed with `npm ci` against a committed lockfile rather than `npx @anthropic-ai/mcpb@2.1.2`: an exact version is not a pin (issue #203). The lockfile pins 55 packages by sha512 integrity and overrides `tmp` to 0.2.7, because the CLI's transitive @inquirer/prompts -> external-editor -> tmp chain otherwise resolves inside the GHSA-52f5-9888-hmc6 / GHSA-ph9p-34f9-6g65 range; `npm audit` reports 0 vulnerabilities after the override. .mcpbignore additionally excludes deps/, fuzz/, .clusterfuzzlite/ and requirements/. deps/ is the git-ignored local pip --target tree: packing a working tree that had bootstrapped the launcher produced 190.1MB / 26951 files where a clean checkout produces 2.1MB / 561 files, so a local pack and a CI pack now agree. .gitignore gains node_modules/, absent until now. Verified locally before commit: npm ci + `mcpb pack` from a `git archive` tree yields hypermnesia-mcp-4.17.0.mcpb (2.1MB, 561 files) containing manifest.json, pyproject.toml, uv.lock, icon.png, README/LICENSE/PRIVACY and 536 mcp_server files, with zero files from tests_py, benchmarks, deps, docs, fuzz, requirements, .github or scripts; the resolved-server.json generator was executed against that bundle and its fileSha256 matches sha256sum. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 2, 2026
cdeust
added a commit
that referenced
this pull request
Aug 2, 2026
…hip it as v4.17.1 (#335) * ci(release): mirror ci.yml network hardening in the release test gate Tag pushes run `release.yml`'s own `test` job, but `ci.yml` triggers on `push: branches: [main]` + `pull_request` (ci.yml:4-8), so no tag has ever reached it. Every hardening pass CI absorbed since 2026-07-27 therefore skipped this file, and the two jobs silently diverged while running the same suite. Release run 30741657854 (v4.17.0) is what that divergence cost: test_spell_alteration.py::test_recall_real_spell_by_name -> pg_recall.py:443 -> reranker.py:109 -> FlashRank's bare `requests.get(..., stream=True)`, which carries no timeout, so a stalled connect hung in `sock.connect` until pytest-timeout killed the suite. HF_HUB_OFFLINE does not reach FlashRank's own fetch path, and reranker.py's `except Exception` cannot engage against a hang that never raises. All five downstream publish jobs were blocked on a tag whose tree had just passed 20 green checks on PR #334; the release shipped zero artifacts. Ported one-for-one from ci.yml:103-115,142-195 — cache + retried prefetch + offline test run, per model: - cache `~/.cache/flashrank`, matching reranker_model.py:104-113's `reranker_cache_dir()` (which honours $XDG_CACHE_HOME); - prefetch the reranker via `ensure_reranker_loaded()` and assert `state == 'loaded'`, so a failed fetch fails the step instead of surfacing later as first-stage-only recall scores (the 2026-07-10 FlashRank incident); - harden the HF prefetch to 5 retries with backoff and drop `continue-on-error`, so a blip cannot leave the cache empty and cascade into a misleading test failure; - run pytest with HF_HUB_OFFLINE / TRANSFORMERS_OFFLINE / CORTEX_RERANKER_OFFLINE, so no model download can happen mid-suite. ci.yml's three tree-sitter steps are deliberately NOT ported: requirements/ release.txt omits tree-sitter and tree-sitter-language-pack (as it omits igraph, leidenalg and texttable), so the AST tests skip in this job and there is no grammar to fetch — porting them would have failed on ImportError. A comment records the corollary: this gate tests a narrower surface than CI, and the three steps must follow if release.txt ever gains that dependency. Verified locally in .venv: `ensure_reranker_loaded()` returns state='loaded'. actionlint is not installed on this machine, so workflow validation was limited to a YAML parse plus review. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * release: v4.17.1 — ship v4.17.0's tree under a version whose workflow works v4.17.0 was tagged but published nothing: its `test` job hung, blocking all five downstream publish jobs, so no GitHub release, no PyPI upload and no .mcpb bundle exist for it. The cause and its fix are the preceding commit. A new patch version rather than a moved tag, because a tag executes the `release.yml` of ITS OWN tree: `v4.17.0` points at 13278df, which carries the unhardened workflow, so a re-run would replay the same hang; and recreating a published tag would break the "tree bit-identical to ae633a8" property the v4.17.0 release decision rests on. House precedent: v3.15.2 abandoned -> v3.15.3. v4.17.1 therefore carries v4.17.0's tree plus the workflow fix — no source change. Version surfaces moved 4.17.0 -> 4.17.1 across the nine sites that carry the release identity: pyproject.toml, server.json (document + pypi package), manifest.json, .claude-plugin/plugin.json, .claude-plugin/marketplace.json (metadata.version + the hypermnesia-mcp entry), uv.lock's root package, package.json, and the generated assets/badge-version.svg. The deprecated `cortex` marketplace entry stays pinned at 4.15.0 — a migration shim, not a shipped version. README's badge alt text, docs/ROADMAP.md's "where the project is today" line, and .bestpractices.json's three version justifications follow. manifest.json matters beyond bookkeeping here: the mcpb-bundle job refuses to pack when its version does not equal the tag (release.yml:419-421), so this is the file the v4.17.1 tag will be checked against. Gates: generate_repo_badges.py --check (4 badges), check_doc_claims.py, and check_marketplace_pins.py all exit 0; every touched JSON parses. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cuts v4.17.0 (116 commits since v4.16.0, 2026-07-24) and closes the gap that
made the MCPB connector unobtainable without cloning the repo.
Version surfaces
Nine sites carry the release identity and all move 4.16.0 → 4.17.0:
pyproject.toml,server.json(document + pypi package),manifest.json,.claude-plugin/plugin.json,.claude-plugin/marketplace.json(
metadata.version+ thehypermnesia-mcpentry),uv.lock's root package,package.json, and the generatedassets/badge-version.svg.The deprecated
cortexmarketplace entry stays at 4.15.0 on purpose — itis the migration shim, not a shipped version.
Gates run locally on the result, all exit 0:
scripts/check_marketplace_pins.pyAll marketplace pins current.scripts/generate_repo_badges.py --checkbadges OK (4 checked)scripts/check_doc_claims.pydoc claims OKCHANGELOG
[Unreleased]had accumulated 3×### Fixedand 2×### Securityacross merges, unlike every published section. Versioned as
[4.17.0]withone sub-section per change type in Keep a Changelog order. Content-preserving
by construction and verified: the sorted multiset of body lines before/after
differs only by the added dependency-bump entry (58 → 59 lines).
MCPB bundle (new
mcpb-bundlejob)manifest.json+.mcpbignorealready described a valid MCPB 0.4 bundle, butnothing built it — v4.14.3 through v4.16.0 shipped zero release assets.
The job packs the bundle on tag and:
manifest.json's version does not match the tag.sha256companiongh attestation verify)server.jsoncarrying both thepypiandmcpbpackage entries
The committed
server.jsonkeeps only the pypi package: themcpbregistryType needs the asset URL and its digest, neither of which exists
before the build runs.
Toolchain is hash-pinned, not version-matched
Installed with
npm ciagainst a committed lockfile rather thannpx @anthropic-ai/mcpb@2.1.2— an exact version is not a pin (#203). Thelockfile pins 55 packages by sha512 integrity and overrides
tmpto0.2.7, because the CLI's transitive
@inquirer/prompts→external-editor→
tmpchain otherwise resolves inside the GHSA-52f5-9888-hmc6 /GHSA-ph9p-34f9-6g65 range.
npm auditreports 0 vulnerabilities after theoverride.
.mcpbignorehardeningAdds
deps/,fuzz/,.clusterfuzzlite/,requirements/.deps/is thegit-ignored local
pip --targettree: packing a working tree that hadbootstrapped the launcher produced 190.1MB / 26951 files where a clean
checkout produces 2.1MB / 561 files — a local pack and a CI pack now
agree.
.gitignorealso gainsnode_modules/, absent until now.Verified locally before commit
npm ci+mcpb packfrom agit archivetree yieldshypermnesia-mcp-4.17.0.mcpb(2.1MB, 561 files) containingmanifest.json,pyproject.toml,uv.lock,icon.png, README/LICENSE/PRIVACY and 536mcp_serverfiles, with zero files fromtests_py,benchmarks,deps,docs,fuzz,requirements,.github,scripts. Theresolved-
server.jsongenerator was executed against that bundle and itsfileSha256matchessha256sum.Not done in this PR
docs/ASSURANCE-CASE.mdstill reads_Last updated: 2026-07-27, against v4.16.0._— bumping that line would assert a review of the assurance caseagainst this tree that has not happened. Left for a deliberate pass.
benchmarks/reproduce.sh, isolated container)have not been run. Per
CLAUDE.mdthey are the only source of truth fora pre-tag floor decision.
🤖 Generated with Claude Code